/* -*-c++-*- */
/* osgGIS - GIS Library for OpenSceneGraph
 * Copyright 2007-2008 Glenn Waldron and Pelican Ventures, Inc.
 * http://osggis.org
 *
 * osgGIS is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */

#ifndef _OSGGIS_TRANSFORM_FEATURE_FILTER_H_
#define _OSGGIS_TRANSFORM_FEATURE_FILTER_H_ 1

#include <osgGIS/Common>
#include <osgGIS/FeatureFilter>
#include <osgGIS/SpatialReference>
#include <osg/Matrix>

namespace osgGIS
{
    /**
     * Transforms feature data by way of spatial reference reprojtion and/or
     * matrix transformation.
     * 
     * If you set an SRS (or set an implicit SRS by way of setUseTerrainSRS(true),
     * the filter performs the SRS transformation before applying any matrix
     * transformations.
     */
    class OSGGIS_EXPORT TransformFilter : public FeatureFilter
    {
        OSGGIS_META_FILTER( TransformFilter );  

    public:
        /**
         * Constructs a new transform filter.
         */
        TransformFilter();

        /**
         * Copy constructor.
         */
        TransformFilter( const TransformFilter& rhs );
        
        /**
         * Constucts a new transform filter.
         *
         * @param matrix
         *      Matrix to use to transform feature data.
         */
        TransformFilter( const osg::Matrix& matrix );


    public: //properties

        /**
         * Sets a transform matrix to use to perform a cartesian transformation
         * on feature shape data.
         *
         * @param xform_matrix
         *      Matrix to use to transform geodata. Note that SRS reprojection
         *      happens before matrix transformation.
         */
        void setMatrix( const osg::Matrix& xform_matrix );

        /**
         * Sets a transform matrix to use to perform a cartesian transformation
         * on feature shape data.
         * 
         * @return A transformation matrix.
         */
        const osg::Matrix& getMatrix() const;

        /**
         * Sets the spatial reference system into which to reproject feature geodata.
         *
         * @param srs
         *      Target spatial reference system.
         */
        void setSRS( const SpatialReference* srs );

        /**
         * Gets the spatial reference system into which the filter will reproject
         * feature geodata.
         *
         * @return
         *      A spatial reference system.
         */
        const SpatialReference* getSRS() const;

        /**
         * Indicates whether the filter should transform features into the terrain's
         * SRS as reported by the FilterEnv at compile time.
         */
        void setUseTerrainSRS( bool value );

        /**
         * Gets whether the filter should use the terrain SRS (as reported by the
         * FilterEnv at compile-time).
         */
        bool getUseTerrainSRS() const;

        /**
         * Sets whether to localize the feature geodata by transforming it so it is
         * relative to the centroid of the graph's working extent. This is the standard
         * way to create a "local origin" for a grid cell so as to avoid precision
         * problems.
         *
         * @param enabled
         *      True to localize geodata; false to not localize
         */
        void setLocalize( bool enabled );

        /**
         * Gets whether to localize the feature geodata by transforming it so it is
         * relative to the centroid of the graph's working extent.
         *
         * @return True to localize, false to not localize.
         */
        bool getLocalize() const;


    public: // script functions

        /**
         * Sets a script that will evaluate to the name of an SRSResource to use for
         * feature data reprojection.
         *
         * @param value
         *      Script that generates an SRSResource name
         */
        void setSRSScript( Script* value );

        /**
         * Gets a script that will evaluate to the  name of an SRSResource to use for
         * feature data reprojection.
         *
         * @return Script that generates an SRSResource name
         */
        Script* getSRSScript() const;

        /**
         * Sets a script that will evaluate to a vec3 to use for cartesian translation
         * of the feature shape data.
         *
         * @param script
         *      Script that generates a vec3
         */
        void setTranslateScript( Script* script );

        /**
         * Gets a script the evaluates to a vec3 to use for cartesian translation of
         * the feature shape data.
         */
        Script* getTranslateScript() const;


    public:
        virtual FeatureList process( FeatureList& input, FilterEnv* env );
        virtual FeatureList process( Feature* input, FilterEnv* env );
        
        virtual ~TransformFilter();

        virtual void setProperty( const Property& p );
        virtual Properties getProperties() const;

    private:
        // properties
        osg::ref_ptr<Script>           srs_script;
        osg::ref_ptr<Script>           translate_script;
        bool                           localize;
        bool                           use_terrain_srs;
        osg::ref_ptr<SpatialReference> srs;

        // transient
        osg::Matrix                    xform_matrix;
        osg::ref_ptr<SpatialReference> working_srs;
    };
}


#endif // _OSGGIS_TRANSFORM_FEATURE_FILTER_H_

